﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#ifndef _UXS_WIN_SPLASH_WINDOW_H
#define _UXS_WIN_SPLASH_WINDOW_H

#pragma once

#include "../OSTypes.h"

#ifdef PLATFORM_WINDOWS_SHELL

#include "Platform.h"

namespace UX_STL
{
namespace _platform_
{
	using namespace winapi;

	
	//
	// Windows Icon
	//

	class UX_EXPORT WindowIcon
	{
	protected:
		HICON	_hIcon;

	public:
		WindowIcon () : _hIcon(null) {}
		~WindowIcon () { Destroy(); }

		bool Load (uint16 uID);
		bool Load (uni_c_string pFileName);

		bool Destroy ();

		HICON Handle () const	{ return _hIcon; }
	};


	
	//
	// Splash Window
	//

	class UX_EXPORT SplashWindow
	{
	private:
		HWND			_hWnd;
		HBITMAP			_hBmp;
		Thread			_sThread;
		UXMath::irect	_sArea;
		
	private:
		bool _CreateWindow ();
		void _DestroyWindow ();
		static void _s_ThreadProc (void *pParametr);

	public:
		SplashWindow ();
		~SplashWindow ();

		bool LoadImage (uint16 uImageId, const UXMath::uvec2 &vDim);
		bool LoadImage (uni_c_string pFileName, const UXMath::uvec2 &vDim);
		bool SetImage (HBITMAP pImage, const UXMath::irect &sArea, bool bCentered = true);

		void Show ();
		void Quit ();
	};



	
//------------------------- WindowIcon ---------------------------//
/*
=================================================
	
=================================================
*/
	inline bool WindowIcon::Load (uint16 uID)
	{
		return Load( MAKEINTRESOURCEA( uID ) );
	}

	inline bool WindowIcon::Load (uni_c_string pFileName)
	{
		_hIcon = LoadIcon( GetModuleHandle( (const char *)null), pFileName.cstr() );
		return _hIcon != null;
	}
	
/*
=================================================
	
=================================================
*/
	inline bool WindowIcon::Destroy ()
	{
		if ( _hIcon == null )
			return true;

		bool	ret = DestroyIcon( _hIcon ) == TRUE;
		_hIcon = null;
		return ret;
	}



//------------------------ SplashWindow --------------------------//
/*
=================================================
	конструктор
=================================================
*/
	inline SplashWindow::SplashWindow ():
		_hWnd(null), _hBmp(null), _sArea(0,0,64,64)
	{
	}

/*
=================================================
	деструктор
=================================================
*/
	inline SplashWindow::~SplashWindow ()
	{
		if ( _hWnd != null )
		{
			PostMessageA( _hWnd, WM_QUIT, 0, 0 );
			_sThread.Wait();
		}
	}
	
/*
=================================================
	загрузить и установить изображение
=================================================
*/
	inline bool SplashWindow::LoadImage (uint16 uImageId, const UXMath::uvec2 &vDim)
	{
		return LoadImage( MAKEINTRESOURCEA( uImageId ), vDim );
	}

	inline bool SplashWindow::LoadImage (uni_c_string pFileName, const UXMath::uvec2 &vDim)
	{
		HBITMAP	h_bmp = LoadBitmap( GetModuleHandle( (const char*)null), pFileName.cstr() );

		if ( h_bmp == null )
			return false;

		return SetImage( h_bmp, UXMath::irect(0, 0, vDim.x, vDim.y), true );
	}

/*
=================================================
	установить изображение на окно
=================================================
*/
	inline bool SplashWindow::SetImage (HBITMAP pImage, const UXMath::irect &sArea, bool bCentered)
	{
		_hBmp	= pImage;
		_sArea	= sArea;

		if ( bCentered )
		{
			const UXMath::uvec2	v_res = WinApiPlatform::ScreenResolution();
			_sArea.x = ( v_res.x - _sArea.w ) / 2;
			_sArea.y = ( v_res.y - _sArea.h ) / 2;
		}
		return true;
	}

/*
=================================================
	показать окно
=================================================
*/
	inline void SplashWindow::Show ()
	{
		_sThread.Create( _s_ThreadProc, this );
		_sThread.Resume();
	}

/*
=================================================
	удалить окно
=================================================
*/
	inline void SplashWindow::Quit ()
	{
		if ( _hWnd != null )
		{
			PostMessageA( _hWnd, WM_QUIT, 0, 0 );
		}
	}

/*
=================================================
	функция в отдельном потоке
=================================================
*/
	inline void SplashWindow::_s_ThreadProc (void *pParameter)
	{
		SplashWindow *	p_splash = (SplashWindow *)pParameter;

		uint	ret = 1;

		if ( p_splash->_CreateWindow() )
		{
			MSG		s_msg		= {0};
			bool			b_looping	= true;

			while ( b_looping )
			{
				if ( PeekMessageA( &s_msg, null, 0, 0, PM_REMOVE ) )
				{
					if ( s_msg.message == WM_QUIT )
						b_looping = false;
					else
					{
						DispatchMessageA( &s_msg );
					}
				}
			}

			p_splash->_DestroyWindow();

			ret = s_msg.wParam;
		}
		//return ret;
	}

/*
=================================================
	создает окно с изображением
=================================================
*/
	inline bool SplashWindow::_CreateWindow ()
	{
		HINSTANCE p_inst = GetModuleHandle( (const char *)null );

		CHECK_ERR( _hBmp != null, "Splash window image not presented" );

		_hWnd = CreateWindowEx( WS_EX_TOPMOST, "STATIC", "",
								WS_POPUP | SS_BITMAP, 0, 0, 0, 0,
								null, null, p_inst, null );

		CHECK_ERR( _hWnd != null, "Can't create splash window" );

		SendMessageA( _hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)_hBmp );
		MoveWindow( _hWnd, _sArea.x, _sArea.y, _sArea.w, _sArea.h, false );

		UpdateWindow( _hWnd );
		ShowWindow( _hWnd, SW_NORMAL );

		LOG( "Splash window created.", e_log_msg::DEBUG );
		return true;
	}

/*
=================================================
	удаляет окно
=================================================
*/
	inline void SplashWindow::_DestroyWindow ()
	{
		if ( _hWnd != null ) {
			CHECK_ERROR_R( DestroyWindow( _hWnd ) == TRUE, "Can't destroy splash window", );
			LOG( "Splash window destroyed.", e_log_msg::SYSTEM );
		}
		_hWnd = null;
	}

//-------------------------------------------------------------------

}	// _platform_
}	// UX_STL

#endif	// PLATFORM_WINDOWS_SHELL

#endif	// _UXS_WIN_SPLASH_WINDOW_H